// 桌面端ipc
// 使用preload.ts
// 统一在这里写，方便管理，其它地方不要出现window.xxx
// 出于安全原因，请勿将 event 参数暴露给渲染器！
// listener中删除了event参数

declare global {
    interface Window {
        ipcRenderer: {
            on: (channel: string, listener: (...args: any[]) => void) => void;
            off: (channel: string, listener: (...args: any[]) => void) => void;
            once: (channel: string, listener: (...args: any[]) => void) => void;
            addListener: (channel: string, listener: (...args: any[]) => void) => void;
            removeListener: (channel: string, listener: (...args: any[]) => void) => void;
            removeAllListeners: (channel?: string) => void;
            send: (channel: string, ...args: any[]) => void;
            invoke: (channel: string, ...args: any[]) => Promise<any>;
            sendSync: (channel: string, ...args: any[]) => any;
            postMessage: (channel: string, message: any, transfer?: MessagePort[]) => void;
            sendToHost: (channel: string, ...args: any[]) => void;
        };
        process: {
            NODE_ENV: 'development' | 'production';
        };
    }
}

const ipcRendererOn = (channel: string, listener: (...args: any[]) => void) => {
    window.ipcRenderer?.on(channel, listener);
};

const ipcRendererOff = (channel: string, listener: (...args: any[]) => void) => {
    window.ipcRenderer?.off(channel, listener);
};

const ipcRendererOnce = (channel: string, listener: (...args: any[]) => void) => {
    window.ipcRenderer?.once(channel, listener);
};

const ipcRendererAddListener = (
    channel: string,
    listener: (...args: any[]) => void,
) => {
    window.ipcRenderer?.addListener(channel, listener);
};

const ipcRendererRemoveListener = (
    channel: string,
    listener: (...args: any[]) => void,
) => {
    window.ipcRenderer?.removeListener(channel, listener);
};

const ipcRendererRemoveAllListeners = (channel?: string) => {
    window.ipcRenderer?.removeAllListeners(channel);
};

const ipcRendererSend = (channel: string, ...args: any[]) => {
    window.ipcRenderer?.send(channel, ...args);
};

const ipcRendererInvoke = async (channel: string, ...args: any[]) => {
    try {
        return await window.ipcRenderer?.invoke(channel, ...args);
    } catch (error) {
        console.error(`Error invoking IPC: ${channel}`, error);
        return null;
    }
};

const ipcRendererSendSync = (channel: string, ...args: any[]) => {
    return window.ipcRenderer?.sendSync(channel, ...args);
};

const ipcRendererPostMessage = (channel: string, message: any, transfer?: MessagePort[]) => {
    window.ipcRenderer?.postMessage(channel, message, transfer);
};

const ipcRendererSendToHost = (channel: string, ...args: any[]) => {
    window.ipcRenderer?.sendToHost(channel, ...args);
};

export const isDesktop = () => {
    return !!window.ipcRenderer;
};

export const getProcessNodeEnv = () => {
    return window?.process?.NODE_ENV;
};

export const ipcRenderer = isDesktop() ? {
    on: ipcRendererOn,
    off: ipcRendererOff,
    once: ipcRendererOnce,
    addListener: ipcRendererAddListener,
    removeListener: ipcRendererRemoveListener,
    removeAllListeners: ipcRendererRemoveAllListeners,
    send: ipcRendererSend,
    invoke: ipcRendererInvoke,
    sendSync: ipcRendererSendSync,
    postMessage: ipcRendererPostMessage,
    sendToHost: ipcRendererSendToHost,
} : {
    on: () => { },
    off: () => { },
    once: () => { },
    addListener: () => { },
    removeListener: () => { },
    removeAllListeners: () => { },
    send: () => { },
    invoke: () => { },
    sendSync: () => { },
    postMessage: () => { },
    sendToHost: () => { },
}
